﻿using System;
using System.Collections.Generic;
using AdvancedGod.Generation;
using AdvancedGod.People;
using AdvancedGod.People.Couples;

namespace AdvancedGod.UserInterface
{
  /// <summary>
  /// Represents god console
  /// </summary>
  public class GodConsole
  {
    #region private static vars
    /// <summary>
    /// collection of exit keys
    /// </summary>
    private static readonly IList<ConsoleKey> ExitKeys
      = new[] { ConsoleKey.F10, ConsoleKey.Q };
    #endregion

    #region private vars
    /// <summary>
    /// printer which will prints all messages
    /// </summary>
    private readonly ConsolePrinter printer;
    #endregion

    #region public methods
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="printer">printer which will print all messages</param>
    public GodConsole(ConsolePrinter printer)
    {
      this.printer = printer;
    }

    /// <summary>
    /// Starts god console
    /// </summary>
    public void Run()
    {
      if (DateTime.Today.DayOfWeek == DayOfWeek.Sunday)
      {
        printer.PrintCanNotWorkAtSunday();
        return;
      }
      printer.PrintWelcome();
      printer.PrintProgramDescription();

      ConsoleKeyInfo key;
      do
      {
        key = Console.ReadKey();
        if (key.Key == ConsoleKey.Enter)
        {
          NextPair();
          printer.PrintProgramDescription();
        }

      } while (!ExitKeys.Contains(key.Key));

      printer.PrintExit();
    }
    #endregion

    #region private methods
    /// <summary>
    /// Generates new pair and tries to couple it
    /// </summary>
    private void NextPair()
    {
      Human firstHuman = RandomGenerator.Instance.CreateRandomHuman();
      Human secondHuman = RandomGenerator.Instance.CreateRandomHuman();

      printer.PrintCouplingHumansDescription(secondHuman, firstHuman);

      try
      {
        IHasName child = null;
        bool couplingOk = CouplingPerformer.Instance.TryCouple(firstHuman, secondHuman);
        if (couplingOk)
        {
          child = ChildCreator.Instance.Create(firstHuman, secondHuman);
        }
        printer.PrintResultChild(child);
      }
      catch (SameSexException ex)
      {
        printer.PrintSameSex(ex.Sex);
      }
      catch (NoAttributeException ex)
      {
        printer.PrintNoAttribute(ex.ClassType1, ex.ClassType2);
      }
    }
    #endregion
  }
}
